package org.sninwo.lnbook.base;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import org.apache.struts2.convention.annotation.ParentPackage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sninwo.lnbook.uitls.LnBookUtils;
import org.sninwo.lnbook.uitls.WebUtils;

import com.opensymphony.xwork2.ActionSupport;

/**
 * 整个框架的Action基类，该类具有以下功能：
 * 1、继承了sninwo-sninwo-lnbook包，这个包定义在struts.xml中，实现 了异常处理。
 * 2、提供了json、xml、text等结果类型的输出。
 * @author linzongxue
 *
 */
@ParentPackage("sninwo-lnbook")
public class BaseAction extends ActionSupport {
	private static final long serialVersionUID = 8026713102486364708L;
	static final Logger logger = LoggerFactory.getLogger(BaseAction.class);
	
	public long[] ids;
	
	/**
	 * 向页面输出成功处理后的json字符串，以success属性值为true表示成功，返回的业务数据保存在data属性中。
	 * 这是应ExtJs的要求。
	 * @param obj 处理成功后返回给页面的业务数据
	 */
	protected String successJson(Object obj){
		Map<String, Object> result = new HashMap<String, Object>(2);
		result.put("success", true);
		result.put("data", obj);
		return json(result);
	}
	
	/**
	 * 向页面输出成功处理后的json字符串，以success属性值为true表示成功。
	 * 这是应ExtJs的要求。
	 */
	protected String successJson(){
		Map<String, Object> result = new HashMap<String, Object>(1);
		result.put("success", true);
		return json(result);
	}

	/**
	 * 向页面输出业务处理有误的json字符串，以success属性值为false表示失败，失败信息保存在errorMsg属性中。
	 * 这是应ExtJs的要求。
	 * @param msg 错误信息，可包含字符串格式，参见String.format方法的使用
	 * @param args 错误信息格式中的参数
	 */
	protected String failureJson(String msg, Object... args){
		if (msg == null) msg = "";
		Map<String, Object> result = new HashMap<String, Object>(2);
		result.put("success", false);
		result.put("errorMsg", String.format(msg, args));
		return json(result);
	}

	/**
	 * 输出json字符串，并设置ContentType为application/json。
	 * @param args 要转换成json的对象，如果只有一个参数则直接转换，否则参数个数必须为偶数，并以奇数参数为属性以偶数参数为值转换。
	 * @return 返回null表示不需要再转向struts2的result
	 */
	protected String json(Object... args){
		WebUtils.getResponse().setContentType("application/json");
		output(LnBookUtils.toJson(args));
		return NONE;
	}
	
	/**
	 * 输出文本，设置ContentType为text/xml
	 * @return none
	 */
	protected String xml(String xml){
		WebUtils.getResponse().setContentType("text/xml");
		output(xml);
		return NONE;
	}

	/**
	 * 输出文本，设置ContentType为text/plain
	 * @param obj
	 * @return none
	 */
	protected String text(Object obj){
		WebUtils.getResponse().setContentType("text/plain");
		return output(obj);
	}
	
	/**
	 * 直接输出文本，不设置ContentType
	 * @param obj
	 * @return none
	 */
	protected String output(Object obj){
		String text = obj.toString();
		try{
			PrintWriter writer = WebUtils.getResponse().getWriter();
			writer.print(text);
			writer.flush();
			logger.debug("输出：[" + WebUtils.getResponse().getContentType() + "] " + 
				(text.length() > 100 ? text.substring(0, 100) + "..." : text));
		}
		catch(Exception e){
			LnBookUtils.throwError(e);
		}
		return NONE;
	}
	
	/**
	 * 输出二进制流，比如图片文件
	 * @return none
	 */
	protected String stream(InputStream stream){
		try{
			BufferedInputStream bufIn = new BufferedInputStream(stream);
			BufferedOutputStream bufOut = new BufferedOutputStream(WebUtils.getResponse().getOutputStream()); 
			byte[] buff = new byte[2048];
			int bytesRead;
			while(-1 != (bytesRead = bufIn.read(buff, 0, buff.length))) {
				bufOut.write(buff,0,bytesRead);
			}
			bufIn.close();
			bufOut.close();
		}
		catch(Exception e){
			LnBookUtils.throwError(e);
		}
		return NONE;
	}
}
